package com.brush.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.brush.common.annotation.DeptPremissScope;
import com.brush.common.constant.Constants;
import com.brush.common.constant.UserConstants;
import com.brush.common.core.domain.entity.SysDept;
import com.brush.common.core.domain.resp.DeptTreeResp;
import com.brush.common.exception.ServiceException;
import com.brush.common.exception.database.PrimaryKeyException;
import com.brush.common.exception.database.RecordNotFoundException;
import com.brush.common.utils.MessageUtils;
import com.brush.common.utils.SecurityUtils;
import com.brush.pig.domain.resp.sow.SowQueryFactoryResp;
import com.brush.system.domain.req.sysdept.SysDeptAddReq;
import com.brush.system.domain.req.sysdept.SysDeptEditReq;
import com.brush.system.domain.req.sysdept.SysDeptReq;
import com.brush.system.domain.resp.sysdept.SysDeptQueryResp;
import com.brush.system.domain.resp.sysdept.SysDeptResp;
import com.brush.system.mapper.SysDeptMapper;
import com.brush.system.service.SysDeptService;
import com.brush.system.service.SysUserService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 18494
 * @description 针对表【sys_dept(部门表)】的数据库操作Service实现
 * @createDate 2024-08-19 10:28:03
 */
@Log4j2
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept>
        implements SysDeptService {

    @Autowired
    private SysUserService sysUserService;

    @DeptPremissScope(deptAlias = "d")
    @Override
    public List<SysDeptResp> search(SysDeptReq req) {
        // 查询到数据库的数据
        List<SysDept> deptList = this.baseMapper.search(req);

        //递归组装树型结构
        return getSysDeptResps(deptList);
    }


    @Override
    public boolean add(SysDeptAddReq req) {
        //先判断当前部门下面是否存在相同的部门名称
        existsDeptName(req.getDeptName(), req.getParentId());


        //查询上级部门
        SysDept parentDept = this.getById(req.getParentId());
        if (Objects.isNull(parentDept)) {
            throw new ServiceException(MessageUtils.message("sysdept.parentId.not.exists"));
        }

        //构造实体类对象
        SysDept dept = new SysDept();
        BeanUtils.copyProperties(req, dept);
        //设定祖级列表
        dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getDeptId());
        dept.setDelFlag(UserConstants.DEPT_NORMAL);
        dept.setCreateBy(SecurityUtils.getUsername());
        dept.setCreateTime(new Date());

        return this.save(dept);
    }

    /**
     * 查询主键查询
     *
     * @param id
     * @return
     */
    @Override
    public SysDeptQueryResp findById(Long id) {
        if (Objects.isNull(id)) {
            throw new PrimaryKeyException();
        }

        SysDept db = this.getById(id);
        if (Objects.isNull(db)) {
            throw new RecordNotFoundException();
        }

        return new SysDeptQueryResp(db);
    }

    /**
     * 修改保存部门信息
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean edit(SysDeptEditReq req) {
        // 上级部门不能是自己"
        if (req.getParentId().equals(req.getDeptId())) {
            throw new ServiceException("修改部门'" + req.getDeptName() + "'失败，上级部门不能是自己");
        }

        SysDept oldDept = this.getById(req.getDeptId());
        if (Objects.isNull(oldDept)) {
            throw new RecordNotFoundException();
        }

        // 部门名称被修改了
        if (!oldDept.getDeptName().equals(req.getDeptName())) {
            existsDeptName(req.getDeptName(), req.getParentId());
        }

        //禁用部门，如果子节点还有启用的，就不能禁用
        if (UserConstants.DEPT_DISABLE.equals(req.getStatus())) {
            LambdaQueryWrapper<SysDept> hasChildQuery = new LambdaQueryWrapper<>();
            hasChildQuery.eq(SysDept::getParentId, req.getDeptId());
            hasChildQuery.eq(SysDept::getStatus, Constants.SUCCESS);
            if (this.baseMapper.selectCount(hasChildQuery) > 0L) {
                throw new ServiceException("部门存在下级部门，不能停用");
            }
        }


        //parent_id发生了变化，子节点也要发生变化
        if (!oldDept.getParentId().equals(req.getParentId())) {

            //判断当前父部门下面的子节点是否有相同的名称
            existsDeptName(req.getDeptName(), req.getParentId());

            SysDept newParentDept = this.getById(req.getParentId());
            //新的祖先列表
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
            oldDept.setAncestors(newAncestors);
            //递归更新子部门的祖先节点
            updateChildDept(req.getDeptId(), newAncestors);
        }

        //再更新本部门信息
        BeanUtils.copyProperties(req, oldDept);
        oldDept.setUpdateBy(SecurityUtils.getUsername());
        oldDept.setUpdateTime(new Date());
        boolean result = this.updateById(oldDept);
        return result;
    }

    private void existsDeptName(String req, Long req1) {
        LambdaQueryWrapper<SysDept> countQuery = new LambdaQueryWrapper<>();
        countQuery.eq(SysDept::getDeptName, req);
        countQuery.eq(SysDept::getParentId, req1);
        if (this.baseMapper.selectCount(countQuery) > 0L) {
            throw new ServiceException(MessageUtils.message("sysdept.deptName.exists"));
        }
    }


    @DeptPremissScope(deptAlias = "d")
    @Override
    public List<SysDeptResp> excludeList(SysDeptReq req) {
        List<SysDept> deptList = this.baseMapper.excludeList(req);

        return getSysDeptResps(deptList);
    }

    @Override
    public boolean deleteById(Long deptId) {

        //查询是否存在子部门
        LambdaQueryWrapper<SysDept> hasChildQuery = new LambdaQueryWrapper<>();
        hasChildQuery.eq(SysDept::getParentId, deptId);
        hasChildQuery.eq(SysDept::getDelFlag, UserConstants.DEPT_NORMAL);
        if (this.baseMapper.selectCount(hasChildQuery) > 0L) {
            throw new ServiceException("存在下级部门,不允许删除");
        }

        //部门是否存在用户
        if (sysUserService.checkDeptExistUser(deptId)) {
            throw new ServiceException("部门存在用户,不允许删除");
        }

        this.checkDeptDataScope(deptId);

        SysDept db = this.getById(deptId);
        if (Objects.nonNull(db)) {
            db.setDelFlag(UserConstants.DEPT_DISABLE);
            db.setUpdateBy(SecurityUtils.getUsername());
            db.setUpdateTime(new Date());
            return this.updateById(db);
        }
        return false;
    }

    @DeptPremissScope(deptAlias = "d")
    @Override
    public List<DeptTreeResp> allDeptTree(SysDeptReq req) {
        List<SysDept> deptList = this.baseMapper.allDeptTree(req);
        List<DeptTreeResp> deptResp= this.buildDeptTreeResp(deptList);
        return deptResp;
    }

    /**
     * 构建树
     * @param deptList
     * @return
     */
    private  List<DeptTreeResp> buildDeptTreeResp(List<SysDept> deptList){
        List<DeptTreeResp> deptTreeRespList=new ArrayList<>();
        //查询根节点
        deptList.stream().filter(p->p.getParentId().intValue()==0).forEach(item->{
            DeptTreeResp root=new DeptTreeResp();
            root.setDeptId(item.getDeptId());
            root.setLabel(item.getDeptName());
            //递归构建子节点
            buildChildrenTreeResp(root, deptList);

            deptTreeRespList.add(root);
        });
        return deptTreeRespList;
    }

    /**
     * 构建子节点
     * @param root
     * @param deptList
     */
    private void buildChildrenTreeResp(DeptTreeResp root, List<SysDept> deptList) {
        List<DeptTreeResp> childrenList=new ArrayList<>();
        //查询子节点
        deptList.stream().filter(p->p.getParentId().intValue()==root.getDeptId().intValue()).forEach(item->{
            DeptTreeResp child=new DeptTreeResp();
            child.setDeptId(item.getDeptId());
            child.setLabel(item.getDeptName());
            //递归构建子节点
            buildChildrenTreeResp(child, deptList);
            childrenList.add(child);
        });

        //有子节点，才加入到上级节点中
        if(childrenList.size()>0){
            root.setChildren(childrenList);
        }
    }

    /**
     * 校验部门是否有数据权限
     *
     * @param deptId 部门id
     */
    public void checkDeptDataScope(Long deptId) {
        boolean isAdmin = SecurityUtils.getLoginUser().getPermissions().contains(Constants.ALL_PERMISSION);

        if (!isAdmin && Objects.nonNull(deptId)) {
            SysDeptReq req = new SysDeptReq();
            req.setDeptId(deptId);

            List<SysDeptResp> deptList = this.search(req);
            if (Objects.isNull(deptList)) {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }
    }

    @Override
    public List<SowQueryFactoryResp> getFactoryList() {
        return this.baseMapper.selectByType();
    }

    /**
     * 查询祖级列表
     * @param deptId
     * @return
     */
    @Override
    public String getAncestors(Long deptId) {
        return this.baseMapper.getAncestors(deptId);
    }


    /**
     * 获取父节点
     * @param l
     * @return
     */
    @Override
    public Long getParent(long l) {
        return this.baseMapper.getParent(l);
    }

    /**
     * 寻找类型
     * @param aLong
     * @return
     */
    @Override
    public String getType(Long aLong) {
        return this.baseMapper.getType(aLong);
    }

    /**
     * 获取栏位ID对应的名称
     * @param deptId
     * @return
     */
    @Override
    public String getName(Long deptId) {
        return this.baseMapper.getName(deptId);
    }

    private List<SysDeptResp> getSysDeptResps(List<SysDept> deptList) {
        //递归组装树型结构
        List<SysDeptResp> treeDeptList = new ArrayList<>();

        //得到所有的dept_id
        List<Long> tempList = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());

        for (SysDept dept : deptList) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                SysDeptResp parent = new SysDeptResp(dept);

                getChildList(deptList, parent);

                treeDeptList.add(parent);
            }
        }

        if (treeDeptList.isEmpty()) {
            treeDeptList = deptList.stream().map(SysDeptResp::new).collect(Collectors.toList());
        }

        log.info("查询完成");

        return treeDeptList;
    }


    /**
     * 根据新的父节点，修改子节点的祖先列表
     *
     * @param deptId
     * @param newAncestors
     */
    private void updateChildDept(Long deptId, String newAncestors) {
        LambdaQueryWrapper<SysDept> updateQuery = new LambdaQueryWrapper<>();
        updateQuery.eq(SysDept::getParentId, deptId);
        List<SysDept> childList = this.list(updateQuery);
        for (SysDept child : childList) {
            //新的祖先列表
            String ancestors = newAncestors + "," + deptId;
            //更新子节点的祖先列表
            child.setAncestors(ancestors);
            child.setUpdateBy(SecurityUtils.getUsername());
            child.setUpdateTime(new Date());
            //更新子节点的祖先列表
            this.updateById(child);
            //递归修改子节点的祖先列表
            updateChildDept(child.getDeptId(), ancestors);
        }
    }


    /**
     * 获取子节点
     *
     * @param deptList 数据库所有值
     * @param parent   父节点
     */
    private void getChildList(List<SysDept> deptList, SysDeptResp parent) {
        List<SysDeptResp> childrenList = new ArrayList<>();

        deptList.stream().filter(item -> item.getParentId().equals(parent.getDeptId()))
                .forEach(item -> {
                    SysDeptResp child = new SysDeptResp(item);
                    // 递归查询子节点
                    getChildList(deptList, child);

                    childrenList.add(child);
                });

        // 有子节点
        if (!childrenList.isEmpty()) {
            parent.setChildren(childrenList);
        }

    }

}




